package com.ecommerce.gateway.filter;

import com.ecommerce.gateway.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Component
public class AuthenticationFilter extends AbstractGatewayFilterFactory<AuthenticationFilter.Config> {

    @Autowired
    private RouteValidator routeValidator;

    @Autowired
    private JwtUtil jwtUtil;

    public AuthenticationFilter() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return java.util.Arrays.asList("excludePaths");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getPath().value();
            System.out.println("AuthenticationFilter processing request for path: " + path);
            
            // 检查是否在排除路径中
            if (config.getExcludePaths() != null && !config.getExcludePaths().isEmpty()) {
                for (String excludePath : config.getExcludePaths()) {
                    if (path.equals(excludePath) || path.startsWith(excludePath + "/")) {
                        System.out.println("Path " + path + " is in exclude list, skipping authentication");
                        return chain.filter(exchange);
                    }
                }
            }
            
            // 检查是否需要认证
            if (routeValidator.isSecured.test(request)) {
                System.out.println("Path requires authentication: " + path);
                
                // 检查是否有Authorization头
                if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
                    System.out.println("Missing authorization header for path: " + path);
                    return onError(exchange, "Missing authorization header", HttpStatus.UNAUTHORIZED);
                }
                
                String authHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
                System.out.println("Authorization header: " + (authHeader != null ? authHeader.substring(0, Math.min(20, authHeader.length())) + "..." : "null"));
                
                if (authHeader != null && authHeader.startsWith("Bearer ")) {
                    authHeader = authHeader.substring(7);
                }
                
                try {
                    // 验证token
                    if (jwtUtil.isInvalid(authHeader)) {
                        System.out.println("Invalid or expired token for path: " + path);
                        return onError(exchange, "Invalid or expired token", HttpStatus.UNAUTHORIZED);
                    }
                    
                    // 提取用户信息
                    String username = jwtUtil.extractUsername(authHeader);
                    String userId = jwtUtil.extractUserIdAsString(authHeader); // 使用字符串类型的用户ID
                    String role = jwtUtil.extractRole(authHeader);
                    
                    System.out.println("Extracted user info - Username: " + username + ", UserId: " + userId + ", Role: " + role);
                    
                    // 在请求头中添加用户信息，传递给下游服务
                    request = exchange.getRequest().mutate()
                            .header("X-User-Name", username)
                            .header("X-User-ID", userId) // 使用X-User-ID而不是X-User-Id
                            .header("X-User-Role", role)
                            .build();
                    
                    // 更新exchange中的请求
                    exchange = exchange.mutate().request(request).build();
                    
                    System.out.println("Added user headers to request for path: " + path);
                    
                } catch (Exception e) {
                    System.out.println("Token validation error for path " + path + ": " + e.getMessage());
                    e.printStackTrace();
                    return onError(exchange, "Invalid token: " + e.getMessage(), HttpStatus.UNAUTHORIZED);
                }
            } else {
                System.out.println("Path does not require authentication: " + path);
            }
            
            return chain.filter(exchange);
        };
    }

    private Mono<Void> onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(httpStatus);
        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        
        String body = "{\"error\": \"" + err + "\", \"status\": " + httpStatus.value() + "}";
        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
        
        return response.writeWith(Mono.just(buffer));
    }

    public static class Config {
        private List<String> excludePaths = new ArrayList<>();
        
        public List<String> getExcludePaths() {
            return excludePaths;
        }
        
        public void setExcludePaths(List<String> excludePaths) {
            this.excludePaths = excludePaths;
        }
    }
}